﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>正则表达式 - 快速参考</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="../css/default.css" rel="stylesheet" type="text/css">
<link href="../css/print.css" rel="stylesheet" type="text/css" media="print">
<style type="text/css">
<!--
.regex {background-color: #FFEED3; font-weight: bold}
.subj {background-color: #DDFFDD}
-->
</style>
</head>
<body>
<h1>正则表达式 - 快速参考</h1>

<h2>基础知识</h2>
<p><strong>不论你在哪</strong>: 通常，正则表达式可以在被搜索字符串中的任意位置找到匹配文本。比如，正则表达式 <span class="regex">abc</span> 可以匹配 <span class="subj">abc</span>123, 123<span class="subj">abc</span>, 和 123<span class="subj">abc</span>xyz 。您也可以使用脱字符号&quot;^&quot;和美元符号&quot;$&quot;把匹配文本锚定(<a href="#anchor">anchor)</a>在这一行的开头和结尾。</p>
<p><strong>神奇的转义</strong>: (<strong>Hsuda</strong>:<em>如果需要匹配的某个字符本身就是元字符(<strong>如：\.*?+[{|()^$</strong> )，正则表达式会如何处理呢？</em>)例如搜索www.xiaonei.com，而需要搜索的文本里的点号在正则表达式里是代表所有字符的元字符。这时我最终使用的正则表达式是www\.xiaonei\.com。通过使用反斜线，让元字符失去特殊含义而成为普通字符。反斜线(\)便是转义符。不过值得注意的是，在字符组内，转义字符无效。</p>
<p><strong>忽略大小写</strong>: 通常，正则表达式不会忽略大小写。但是这会给我们带来一些困扰，比如我们在处理HTML文档的时候，H1和h1是一个意思，但正则表达式却无法知道。这个时候我们可以使用选项&quot;i&quot;让正则表达式忽略大小写。比如<span class="regex">i)abc</span>可以忽略大小写去搜索abc。参照 <a href="../commands/RegExMatch.htm#Options">options</a> 来获取更多选项信息。</p>
<h2>通用的元字符及使用方法： </h2>
<table border="1" width="100%" cellspacing="0" cellpadding="3" bordercolor="#C0C0C0">
	<tr>
		<td align="center"><strong>.</strong></td>
		<td><a name="dot"></a>点号 匹配单个任意字符(除了新行：换行符('r)和回车符('n))。比如，<span class="regex">ab.</span> 匹配 <span class="subj">abc</span>和<span class="subj">abz</span>及<span class="subj">ab_</span>。</td>
	</tr>
	<tr>
		<td align="center"><strong>*</strong></td>
		<td><p>星号 可以匹配任意多次(字符，字符组(<a href="#class">class</a>)，单元(<a href="#subpat">subpattern</a>))，也可能不匹配。比如 a* 可以匹配ab 也可以匹配aaaab 。它还可以匹配甚至不包含a的字符串。</p>
      <p><strong>通配符:</strong> AHK里自由的组合莫过于 点号-星号 的组合。它可以匹配任意多的任意字符，也可以匹配0个字符(当然，除了新行：换行符('r)和回车符('n))。比如： <span class="regex">abc.*123</span> 匹配 <span class="subj">abcAnything123</span> 或者 <span class="subj">abc123</span>。</p>		  </td>
	</tr>
	<tr>
	  <td align="center"><strong>?</strong></td>
	  <td><p>问号 容许匹配一次(字符，字符组(<a href="#class">class</a>)，单元(<a href="#subpat">subpattern</a>))，但非必须。您可以理解为&ldquo;之前的那项是可选的&rdquo;。比如， <span class="regex">colou?r</span> 可以</p>
      <p>匹配 <span class="subj">color</span>和<span class="subj">colour</span> 因为&quot;u&quot;是可选的。</p></td>
  </tr>
	<tr>
	  <td align="center"><strong>+</strong></td>
	  <td>加号 至少需要匹配一次(字符，字符组(<a href="#class">class</a>)，单元(<a href="#subpat">subpattern</a>))，至多可能任意多次。比如 <span class="regex">a+</span> 匹配 <span class="subj">a</span>b 和 <span class="subj">aaa</span>b。但是在开头必须至少有一个a，这就是他与星号有区别的地方。</td>
  </tr>
	<tr>
	  <td align="center">{min,max}</td>
	  <td><p>区间量词 至少需要min次(字符，字符组(<a href="#class">class</a>)，单元(<a href="#subpat">subpattern</a>))，至多容许max次。比如，a{1,2}可以匹配ab 但仅仅只能匹配aaab中的前两个a。</p>
      <p>另外，{3}意味着准确地匹配3次，{3,}意味着3次或者更多。注意：您所指定的数字必须小于65536，并且第一个数字要小于第二个数字。（地球人都知道为什么~）</p></td>
  </tr>
	<tr>
	  <td align="center"><strong>[...]</strong></td>
	  <td><p><a name="set"></a><a name="class"></a><strong>字符组:</strong> (<strong>Hsuda</strong>:<em>如果我们要搜索的是单词&quot;grey&quot;而又不确定它是否写作&quot;gray&quot;，便应当使用字符组。</em>)在方括号中列出期望匹配的字符。[abc]可以匹配a或b或c。我们也可以使用连字符&quot;-&quot;来表示一个范围；比如[a-z]就意味着可以匹配所有的小写字母，很有趣，不是么？</p>
	    <p><strong>Hsuda</strong>:<em>下面所介绍的\d \w &hellip;&hellip;都是一种特殊的字符组。</em></p>
        <p>与单个字符一样，您可以使用 *, ?, +, or {min,max}这些量化符号跟在字符组的后面。效果同上面的介绍。 比如<span class="regex">[0-9]+</span>匹配一个或者更多的数字，所以能够匹配xyz123而不能匹配abcxyz。</p>            
        <p>在字符组你既可以罗列你期望匹配的字符也可以使用字符序列，或者将二者组合使用。比如 <span class="regex">[a-zA-Z0-9_]</span> 可以匹配数字字母下划线。</p>
      <p><strong>Hsuda</strong>:<em>我们通常所说的字符组在POSIX标准中被称为方括号表达式(bracket expression)。POSIX中术语&quot;字符组&quot;指的是在方括号表达式内部使用的一种特殊的功能(special feature)，而我们可以认为它们是Unicode的字符属性的原型。</em></p>
      <p>POSIX标准中规定的形式是 [[:xxx:]] ，xxx可以上下面的单词来代替：</p>
      <p>alnum 字母字符和数字字符</p>
      <p>alpha 字母</p>
      <p>ascii 0-127</p>
      <p>blank 空格和制表符</p>
      <p>cntrl 控制字符</p>
      <p>digit 数字0-9</p>
      <p>xdigit 16进制数字</p>
      <p>print 类似graph但包含空白字符</p>
      <p>graph 非空白字符(即空白字符，控制字符之外的字符)</p>
      <p>punct 标点符号</p>
      <p>lower 小写字母</p>
      <p>upper 大写字母</p>
      <p>space 所有的空白字符</p>
      <p>word 单词字符，参考<a href="#word">\w</a></p>
      
      <p>Within a character class, characters do not need to be escaped except when they have special meaning inside a class; e.g. <span class="regex">[\^a]</span>, <span class="regex">[a\-b]</span>, <span class="regex">[a\]]</span>, and <span class="regex">[\\a]</span>.</p></td>
      </td>
  </tr>
	<tr>
	  <td align="center"><strong>[^...]</strong></td>
	  <td>排除型字符组 匹配任何未列出的字符。比如[^1-6]匹配除了1到6以外的任何字符。其他特性与字符组相同。</td>
  </tr>
	<tr>
	  <td align="center"><strong>\d</strong></td>
	  <td>匹配单个数字 等价于 [0-9]。相反的 \D 匹配非数字字符 等价于 [^0-9]。这个和下面介绍的那两个都可以用在字符组里。比如[\d.-]可以匹配所有数字，点号，和连字符。</td>
  </tr>
	<tr>
	  <td align="center"><strong>\s</strong></td>
	  <td>匹配空白字符 通常等价于[ \f\n\r\t\v]即匹配空白符，空格，制表，换行。相反的 \S匹配非空白字符。</td>
  </tr>
	<tr>
	  <td align="center"><strong>\w</strong></td>
	  <td><a name="word"></a>匹配单词中的字符，等价于[0-9a-zA-Z_]。相反的\W匹配非单词字符 等价于[^0-9a-zA-Z]。</td>
  </tr>
	<tr>
	  <td align="center"><strong>^<br>
        $</strong></td>
	  <td><p><a name="anchor" id="anchor"></a>脱字符号&quot;^&quot;和美元符号&quot;$&quot;被称为锚点是因为他们并不会匹配实际的文本，而是寻找文本中的位置。(<strong>Hsuda:</strong><em>我把锚点归类为&ldquo;零长度断言&rdquo;</em>)</p>
	    <p><span class="regex">^</span>(脱字符)匹配需要搜索的文本的起始位置。比如： <span class="regex">^abc</span> 匹配 <span class="subj">abc</span>123 而不能 123abc。	    </p>
	    <p><span class="regex">$</span> 美元符号 匹配目标字符串的末尾。比如<span class="regex">abc$</span> 匹配 123<span class="subj">abc</span> 而不是 abc123。</p>
      <p>两个锚点可以组合使用，比如<span class="regex">^abc$</span> 只能匹配abc(在abc的前面和后面不能有任何字符)。</p>
      <p>对于有很多行的被搜索文本，我们可以使用  <a href="../commands/RegExMatch.htm#Multiline">&quot;m&quot; 选项 </a>使得锚点可以用作搜索每一行而不是把所有行当作整体来搜索。比如<span class="regex">m)^abc$</span> 可以匹配 123`r`n<span class="subj">abc</span>`r`n789 。但是如果缺少 &quot;m&quot; 选项，这是不可以匹配的。</p></td>
  </tr>
	<tr>
	  <td align="center"><strong>\b</strong></td>
	  <td>\b 代表&quot;单词分界符(word boundary)&quot;，单词分界符的作用与行锚点一样，也是匹配字符串中的某些位置。它要求当前字符的状态是一个单词字符(\w)而它之前的与它相反。我们使用\b能有效地避免在匹配过程中遇到一个单词属于另一个单词时造成的麻烦。比如： <span class="regex">\bcat\b</span>不能匹配catfish而仅仅只能匹配cat。\B则起到的是完全相反的作用。</td>
  </tr>
	<tr>
	  <td align="center"><strong>|</strong></td>
	  <td>竖线将两个或者更多的选项分隔开来。选项中的任意一项满足条件便可以完成匹配。比如<span class="regex">gray|grey</span> 可以匹配 <span class="subj">gray</span>和<span class="subj">grey</span>。相似的，表达式 <span class="regex">gr(a|e)y</span> 所产生的作用与上面这个例子一样。</td>
  </tr>
	<tr>
	  <td align="center"><strong>(...)</strong></td>
	  <td><p><a name="subpat"></a>将表达式放入括号里通常应用于：</p>
	    <ul>
	      <li>确定赋值的类型。比如<span class="regex">(Sun|Mon|Tues|Wednes|Thurs|Fri|Satur)day</span>可以匹配任何一天的名字。</li>
	      <li>应用 <span class="regex">*</span>, <span class="regex">?</span>, <span class="regex">+</span>, 或 <span class="regex">{min,max}</span> 来量化多于一个的字符。比如<span class="regex">(abc)+</span> 可以匹配一连串的&ldquo;abc&rdquo;，他可以匹配abcabc而不能匹配ab123或 bc123。</li>
          <li>捕获子表达式的值就像捕获<span class="regex">abc<span class="red">(.*)</span>xyz</span> 中点号所匹配的部分。比如<a href="../commands/RegExMatch.htm">RegExMatch()</a>在他的输出数组(<a href="../commands/RegExMatch.htm#Array">output array</a>)中存储子表达式所匹配的值。相似的，在<a href="../commands/RegExReplace.htm">RegExReplace()</a> 中，允许我们使用类似$1这样的回溯(<a href="../commands/RegExReplace.htm#BackRef">backreferences</a>)将匹配每个子表达式的文本重新插入到结果中。不过捕获并不总是好事，为了避免捕获带来的烦恼，正则表达式提供了非捕获型括号，在左边的括号的后面写上<span class="regex">?:</span> 作为前两个字符，比如(?:.*) (?:abc)。</li>
	      <li>在工作状态下改变选项(<a href="../commands/RegExMatch.htm#Options">options</a>)。比如 <span class="regex">(?im)</span> 能够让表达式的剩余部分忽略大小写选项和多行选项(如果它在一个子表达式中，则改变这个子表达式的)。相反的， <span class="regex">(?-im)</span> 将把这两个参数全部关闭。除了 DPS`r`n`a 外支持所有的选项。</li>
	    </ul></td>
  </tr>
	<tr>
	  <td align="center"><strong>\t<br>
  \r<br>
  etc.</strong></td>
	  <td><p>这些转义字符代表特殊字符。最常见的是\t代表制表符，\r代表回车，\n代表换行。在AutoHotkey里，这里例子里的反斜线可以用重音符号&quot; ` &quot;来代替(当然是为了方便群众)。像\xhh这种形式的转义字符也是支持的，hh则是代表ANSI字符的十六进制数(00-FF)。</p>
      <p>在 v1.0.46.06以上的版本中， <span class="regex">\R</span> 代表&quot;任何形式的单个换行符&quot;，与之功能相同的是 <a href="../commands/RegExMatch.htm#NEWLINE_ANY">`a option</a>(然而，\R在字符组(<a href="#class">character class</a>)内仅仅是字母&quot;R&quot;)。在In v1.0.47.05以上的版本中，在表达式的前面指定(*BSR_ANYCRLF)可以让 <span class="regex">\R</span> 匹配CR LF 和 CRLF。比如：<span class="regex">im)(*BSR_ANYCRLF)abc\Rxyz</span>。</p></td>
  </tr>
</table>
<p><strong>匹配优先模式</strong>:通常， <span class="regex">*</span>, <span class="regex">?</span>, <span class="regex">+</span>, 和 <span class="regex">{min,max}</span>是匹配优先量词因为他们都是尽可能多地去匹配字符。</p>
<p><strong>Hsuda</strong>:<em>这里插播一个例子，对于匹配优先模式，我们将遇到一个很常见的陷阱。比如，我们要搜索的句子是</em></p>
<p> <em>They call me &quot;Hsudatalks&quot; or &quot;Freedom&quot;.</em></p>
<p class="CodeCom">我希望搜索第一对引号里的内容，可能会产生这样的表达式&quot;.+&quot;，可是由于*是匹配优先的量词，我们得到的结果是</p>
<p class="CodeCom">&quot;Hsudatalks&quot; or &quot;Freedom&quot;</p>
<p class="CodeCom">这明显不是我们所期望的结果。那该怎么办呢？请看下面的帮助：</p>
<p>在他们后面使用问号则可以让他们尽可能少的匹配字符。那上面的例子我们采用&quot;.+?&quot;，所得到的便是&quot;Hsudatalks&quot;。</p>
<p>例：表达式&lt;.+&gt;所表示的意思是先搜索&lt;，在匹配一个或者更多的任意字符，后面跟着一个&gt;。在匹配时会出现 <span class="subj"><span class="red"><strong>&lt;</strong></span>em&gt;text&lt;/em<span class="red"><strong>&gt;</strong></span></span>，为了避免这种情况，我们使用<span class="regex">&lt;.+<span class="red">?</span>&gt;</span> 使得表达式仅仅只会匹配标记<span class="subj"><span class="red"><strong>&lt;</strong></span>em<span class="red"><strong>&gt;</strong></span></span>。</p>
<p><strong>顺序环视和逆序环视</strong>:  <span class="regex">(?=...)</span>，<span class="regex">(?!...)</span>，<span class="regex">(?&lt;=...)</span> 和 <span class="regex">(?&lt;!...)</span> 被成为环视，因为他们都是形容一个匹配条件而不消耗任何字符。比如：<span class="regex">abc(?=.*xyz) </span>匹配右边的某个地方存在字符xyz的字符abc(如果不存在，便不能匹配)。 <span class="regex">(?=...)</span>被称为肯定顺序环视，因为他需要指定的字符在后面存在才能够完成匹配过程。相反的，<span class="regex">(?!...)</span>是否定顺序环视，因为他是在不存在指定字符的条件下的条件下完成匹配。相似的，<span class="regex">(?&lt;=...)</span> 和<span class="regex">(?&lt;!...)</span> 被称为肯定和否定的逆序环视，因为他们是在当前位置的左边寻找指定的字符存在或者不存在。逆序要比顺序更加局限，因为他不支持<span class="regex">*,?和+</span>这样的量词。</p>
<p><strong>相关</strong>： 正则表达式由 <a href="../commands/RegExMatch.htm">RegExMatch()</a>, <a href="../commands/RegExReplace.htm">RegExReplace()</a>和<a href="../commands/SetTitleMatchMode.htm">SetTitleMatchMode</a>支持。</p>
<p><strong>最后</strong>：尽管这个页面介绍了正则表达式中最常用的元字符和一些特性，但是还有比如条件子表达式等相当一部分的其他特性您期望了解的。完整的PCRE手册请访问 <a href="http://www.pcre.org/pcre.txt">www.pcre.org/pcre.txt</a> 。(<strong>Hsuda</strong>:<em>写到这里，发现AHK里的正则表达式原来用的是PCRE的库，关于PCRE，大家需要了解的是这是个地地道道的传统NFA引擎的正则库，所以，在编写正则表达式的时候是很考验您的优化功力的</em>) </p>

</body>
</html>
